import numpy as np

from init import *
from sklearn.decomposition import PCA
from skfuzzy.cluster import cmeans
from scipy.optimize import minimize
import copy
from collections import Counter
from sklearn.preprocessing import MinMaxScaler

from init import *
from method import *
import geatpy as ea
import pandas as pd

plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False


def get_feature(img_data, flag, v, h, k):
    '''
    对图像的特征进行提取
    :param img_data: 图像信息
    :param flag: 奇数点还是偶数点
    :return:
    '''
    row, col = img_data.shape
    size = int((row * col) / 2)

    errolist = np.zeros(row * col)

    index = 0
    print('k', k)
    F = np.zeros((k, size))
    for i in range(2, row - 2):
        for j in range(2, col - 2):
            # 像素上下左右四个像素
            v1 = int(img_data[i - 1][j])
            v2 = int(img_data[i][j - 1])
            v3 = int(img_data[i + 1][j])
            v4 = int(img_data[i][j + 1])
            # 选中点
            x = int(img_data[i][j])
            # 其他九个点
            v5 = int(img_data[i - 2][j - 1])
            v6 = int(img_data[i - 1][j - 2])
            v7 = int(img_data[i + 1][j - 2])
            v8 = int(img_data[i + 2][j - 1])
            v9 = int(img_data[i + 2][j + 1])
            v10 = int(img_data[i + 1][j + 2])
            v11 = int(img_data[i - 1][j + 2])
            v12 = int(img_data[i - 2][j + 1])
            # 左梯度和右梯度
            lg = np.array([[v5 - v1, v2 - v1], [v1 - v4, v3 - v4], [v2 - v3, v8 - v3], [v6 - v2, v7 - v2]])
            rg = np.array([[v12 - v1, v4 - v1], [v11 - v4, v10 - v4], [v4 - v3, v9 - v3], [v1 - v2, v3 - v2]])

            # 从特征11开始为wang以外的特征
            t0 = np.array(
                [int(img_data[i][j - 1]), int(img_data[i][j + 1]),
                 np.round(int(img_data[i][j - 1] + img_data[i][j + 1]) / 2)])
            t45 = np.array(
                [img_data[i][j + 1], img_data[i + 1][j], np.round(int(img_data[i][j + 1] + img_data[i + 1][j]) / 2)])
            t90 = np.array(
                [img_data[i + 1][j], img_data[i - 1][j], np.round(int(img_data[i + 1][j] + img_data[i - 1][j]) / 2)])
            t135 = np.array(
                [img_data[i][j - 1], img_data[i + 1][j], np.round(int(img_data[i][j - 1] + img_data[i + 1][j]) / 2)])
            u = np.mean([int(img_data[i][j - 1] + img_data[i][j + 1]) / 2,
                         int(img_data[i][j + 1] + img_data[i + 1][j]) / 2,
                         int(img_data[i + 1][j] + img_data[i - 1][j]) / 2,
                         int(img_data[i][j - 1] + img_data[i + 1][j]) / 2])
            t1 = np.sum(np.square(t0 - u))
            t2 = np.sum(np.square(t45 - u))
            t3 = np.sum(np.square(t90 - u))
            t4 = np.sum(np.square(t135 - u))

            # 特征14
            if j - 3 > 0 and j + 3 < 511:
                x7arr = np.array([img_data[i][j - 3], img_data[i][j - 1], img_data[i][j + 1], img_data[i][j + 3]])
            else:
                x7arr = np.array([img_data[i][j - 1], img_data[i][j + 1]])
            u1 = np.mean(x7arr)
            # 特征15
            if i - 3 > 0 and i + 3 < 511:
                x8arr = np.array([img_data[i - 3][j], img_data[i - 1][j], img_data[i + 1][j], img_data[i + 3][j]])
            else:
                x8arr = np.array([img_data[i - 1][j], img_data[i + 1][j]])
            u2 = np.mean(x8arr)
            # 特征16
            Vu = np.array([img_data[i - 1][j - 2], img_data[i - 2][j - 1], img_data[i][j - 1],
                           img_data[i - 1][j], img_data[i - 2][j + 1], img_data[i][j + 1],
                           img_data[i - 1][j + 2]]
                          )
            Vb = np.array([img_data[i + 1][j - 2], img_data[i][j - 1], img_data[i + 2][j - 1],
                           img_data[i + 1][j], img_data[i][j + 1], img_data[i + 2][j + 1],
                           img_data[i + 1][j + 2]]
                          )
            Hl = np.array([img_data[i - 2][j - 1], img_data[i - 1][j - 2], img_data[i - 1][j],
                           img_data[i][j - 1], img_data[i + 1][j - 2], img_data[i + 1][j],
                           img_data[i + 2][j - 1]]
                          )
            Hr = np.array([img_data[i - 2][j + 1], img_data[i - 1][j], img_data[i - 1][j + 2],
                           img_data[i][j + 1], img_data[i + 1][j], img_data[i + 1][j + 2],
                           img_data[i + 2][j + 1]]
                          )
            # 特征17
            V10 = np.array([img_data[i - 2][j - 1], img_data[i - 2][j + 1], img_data[i - 1][j - 2],
                            img_data[i - 1][j], img_data[i - 1][j + 2], img_data[i][j - 1],
                            img_data[i][j + 1], img_data[i + 1][j - 2], img_data[i + 1][j],
                            img_data[i + 1][j + 2], img_data[i + 2][j - 1], img_data[i + 2][j - 1]])

            u3 = np.mean(V10)

            # 特征二十
            point1 = np.mean([img_data[i - 2][j - 1], img_data[i - 1][j - 2], img_data[i][j - 1], img_data[i - 1][j]])
            point2 = np.mean([img_data[i - 1][j], img_data[i - 2][j + 1], img_data[i - 1][j + 2], img_data[i][j + 1]])
            point3 = np.mean([img_data[i + 1][j - 2], img_data[i][j - 1], img_data[i + 1][j], img_data[i + 2][j - 1]])
            point4 = np.mean([img_data[i + 1][j], img_data[i + 2][j + 1], img_data[i][j + 1], img_data[i + 1][j + 2]])
            Varr = np.array([v1, v2, v3, v4, point1, point2, point3, point4])
            temp1 = np.sign(Varr - img_data[i][j])
            temp = np.where(np.sign(Varr - img_data[i][j]) == -1)[0]
            temp1[temp] = 0

            # # 特征
            f1 = np.max([v1, v2, v3, v4])
            f2 = np.min([v1, v2, v3, v4])
            sod1 = abs(v2 + v4 + v5 + v12 - 4 * v1)
            sod2 = abs(v1 + v3 + v6 + v7 - 4 * v2)
            sod3 = abs(v2 + v4 + v8 + v9 - 4 * v3)
            sod4 = abs(v1 + v3 + v10 + v11 - 4 * v4)
            f3 = np.sum([sod1, sod2, sod3, sod4])
            f4_arr = [abs(v1 - v2), abs(v2 - v3), abs(v3 - v4), abs(v4 - v1)]
            f4 = np.sum(f4_arr)
            # p2 = np.average([abs(v1 - v2), abs(v2 - v3), abs(v3 - v4), abs(v4 - v1)])
            p1 = (math.modf(np.average([v1, v2, v3, v4])))[0]
            p = np.ceil(np.average([v1, v2, v3, v4])) if p1 >= 0.5 else np.floor(np.average([v1, v2, v3, v4]))
            # f5_arr = [p2 - abs(v1 - v2), p2 - abs(v2 - v3), p2 - abs(v3 - v4), p2 - abs(v4 - v1)]
            # f5 = np.average(np.square(f5_arr))
            # f6_arr = [p - v1, p - v2, p - v3, p - v4]
            # f6 = np.average(np.square(f6_arr))
            f5_arr = [abs(v6 - v7), abs(v5 - v2), abs(v2 - v8), abs(v1 - v3), abs(v12 - v4), abs(v4 - v9),
                      abs(v11 - v10), abs(v5 - v12), abs(v6 - v1), abs(v1 - v11), abs(v2 - v4), abs(v7 - v3),
                      abs(v3 - v10), abs(v8 - v9)]
            f5 = np.sum(f5_arr)
            new_f5 = np.sum(np.square(f4_arr - np.mean(f4_arr))) / 4
            f6_arr = [abs(p - v1), abs(p - v2), abs(p - v3), abs(p - v4), abs(p - v5), abs(p - v6), abs(p - v7),
                      abs(p - v8), abs(p - v9), abs(p - v10), abs(p - v11), abs(p - v12)]
            f6 = np.sum(f6_arr)
            new_f6 = np.sum(np.squeeze(np.array([v1, v2, v3, v4]) - p)) / 4
            f7 = np.sum(np.sqrt(np.sum(np.square(lg), axis=1)))
            f8 = np.sum(np.sqrt(np.sum(np.square(rg), axis=1)))
            gradDiff = []
            gradDiff2 = []
            for s in range(3):
                for q in range(s, 4):
                    gradDiff.append(lg[s] - lg[q])
                    gradDiff2.append(rg[s] - rg[q])
            # print(gradDiff, gradDiff2)
            gradDiff = np.array(gradDiff)
            gradDiff2 = np.array(gradDiff2)
            f9 = np.sum(np.sqrt(np.sum(np.square(gradDiff), axis=1)))
            f10 = np.sum(np.sqrt(np.sum(np.square(gradDiff2), axis=1)))

            f11 = np.sqrt(v[i][j] ** 2 + h[i][j] ** 2)
            f12 = np.sqrt(np.sum([t1, t2, t3, t4]))
            f13 = np.mean([v1, v2, v3, v4])
            f14 = np.sum(x7arr - u1)
            f15 = np.sum(x8arr - u2)
            f16 = np.sum([np.abs(Vu - Vb), np.abs(Hl - Hr)])
            f17 = np.sum(np.abs(V10 - u3))
            f18 = np.abs(img_data[i - 2][j + 1] - img_data[i - 1][j]) \
                  + np.abs(img_data[i - 1][j] - img_data[i][j - 1]) \
                  + np.abs(img_data[i][j - 1] - img_data[i + 1][j - 2]) \
                  + np.abs(img_data[i - 1][j + 2] - img_data[i][j - 1]) \
                  + np.abs(img_data[i][j - 1] - img_data[i + 1][j]) \
                  + np.abs(img_data[i + 1][j] - img_data[i + 2][j - 1])
            f19 = np.abs(img_data[i - 2][j + 1] - img_data[i - 1][j]) \
                  + np.abs(img_data[i - 1][j] - img_data[i][j - 1]) \
                  + np.abs(img_data[i][j - 1] - img_data[i + 1][j - 2]) \
                  + np.abs(img_data[i - 1][j + 2] - img_data[i][j + 1]) \
                  + np.abs(img_data[i][j + 1] - img_data[i + 1][j]) \
                  + np.abs(img_data[i + 1][j] - img_data[i + 2][j - 1])
            f20 = np.sum(temp1)


            fnew1 = np.var([v1,v2,v3,v4],ddof=0)
            temps = np.append([v2,v1,v4,v3],v2)
            fnew2 =np.var( abs(np.diff(temps)),ddof=0)
            # print(fnew1,fnew2)
            a = np.array([f1, f2, f4, f3, f10, f9, f8, f7, f5, f6, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20])
            # datakey = np.array([4, 5, 9, 1, 3, 16, 0, 2, 8, 10],dtype=int)
            # datakey = np.array([4, 5, 9, 1, 3, 16, 0, 2, 8, 10], dtype=int)
            # temp = datakey[dataset]
            # a = a[datakey]
            # a = np.array([ f2, f4, f3, f10, f9, f8, f7, f5, f6])
            # a = np.array([f1, f2, f4, f3, f10, f9, f8, f7, f5, f6])
            # a = np.array([f1, f2, fnew1, fnew2, f3, f8, f7, f4, f10, f9])
            # a = np.array([f1, f2, f3, f4, new_f5, new_f6, f7, f8, f9, f10])
            if np.mod(i + j, 2) == 0 and flag == 0:
                F[:, index] = a
                errolist[index] = int(img_data[i][j]) - int(p)
                index += 1

            if np.mod(i + j, 2) == 1 and flag == 1:
                F[:, index] = a
                errolist[index] = int(img_data[i][j]) - int(p)
                index += 1
    F = F[:, :index]
    errolist = errolist[:index]

    return F, errolist, index


def getcmeans(F):
    pca = PCA(n_components=3)
    data = pca.fit_transform(F.T)
    data = np.array(data)
    # enter, u, u0, d, jm, p, fpc = cmeans(data.T, m=2, c=16, error=0.5, maxiter=10000)
    print(data.T)
    center, u, u0, d, jm, p, fpc = cmeans(data.T, 16, 2, error=0.00001, maxiter=100)
    label = np.argmax(u, axis=0)
    print('label', label)
    print(np.unique(label))
    return label


def V(arg):
    em, cm = arg
    emeans = em - np.mean(em)
    emstd = np.sqrt(np.sum(np.square(emeans)))
    vx = lambda x: np.sum(
        em * (np.dot(np.array([x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9]]).reshape(-1, 10), cm))) \
                   / (np.sqrt(np.sum(np.square(
        np.dot(np.array([x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9]]).reshape(-1, 10), cm) - np.mean(
            np.dot(np.array([x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9]]).reshape(-1, 10),
                   cm))))) * emstd)

    return vx


def Cm(comlex, em,weightsize):
    bond =((-255,255),)*weightsize
    # x0 = np.asarray((-255, 240, -81, 213, 202, -159, 34, 29, 93, 100)).reshape(-1, 10)
    # x0 = np.asarray((-100, 100, 10, 20, 30, 40, 50, 60, 80, 100)).reshape(-1, 10)
    # x0 = np.asarray((253.0	,-239.0,	-206.0,	62.0	,-117.0,	-107.0,	38.0,	31.0	,-20.0,	-57.0	)).reshape(-1, 10)
    # x0 = np.asarray((1, 2, 3, 4, 5, 6, 7, 8, 9, 10)).reshape(-1, 10)
    x0 = np.asarray((1,)*weightsize).reshape(-1, weightsize)
    # x0 = np.ones(10)
    # x0 =np.random.randint(-255,255,[10])
    print(x0)

    # em = errolist - np.mean(errolist)
    # size = em.shape[0]
    # em = em.reshape(-1, size)
    # em2 = np.sqrt(np.sum(np.square(errolist - np.mean(errolist))))
    # v = lambda x: -(np.dot(em, (
    #             np.dot(np.array([x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9]]).reshape(-1, 10),
    #                    cm) - np.mean(
    #         np.dot(np.array([x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9]]).reshape(-1, 10),
    #                cm))).T)) /    (np.std(np.dot(np.array([x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9]]).reshape(-1, 10), cm),
    #         ddof=1) * np.sqrt(len(errolist)) * np.sqrt(len(errolist)) * np.std(errolist, ddof=1))

    #       (em2 * np.sqrt(np.sum(np.square(np.dot(np.array([x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9]]).reshape(-1, 10), cm) - np.mean(
    # np.dot(np.array([x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9]]).reshape(-1, 10), cm))))))

    # v = lambda x:-(np.sum(em*(np.dot(np.array([x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9]]).reshape(-1, 10),
    #                    cm) - np.mean(
    #         np.dot(np.array([x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9]]).reshape(-1, 10),
    #                 cm)))))/(np.std(np.dot(np.array([x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9]]).reshape(-1, 10), cm),
    #         ddof=1) * np.sqrt(len(errolist))*np.sqrt(len(errolist))*np.std(errolist))
    emeans = em - np.mean(em)
    emstd = np.sqrt(np.sum(np.square(emeans)))
    # print('emstd', emstd)
    # vx = lambda x: -np.sum(
    #     em * (np.dot(np.array([x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9]]).reshape(-1, 10), comlex))) \
    #                / (np.sqrt(np.sum(np.square(
    #     np.dot(np.array([x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9]]).reshape(-1, 10), comlex) - np.mean(
    #         np.dot(np.array([x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9]]).reshape(-1, 10),
    #                comlex)))))*emstd)
    # vx = lambda x: -(np.corrcoef(abs(em), np.dot(
    #     np.array([x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19]]).reshape(-1, weightsize), comlex)))[0][1]
    vx = lambda x: -(np.corrcoef(abs(em), np.dot(
        np.array([x[i] for i in range(weightsize)]).reshape(-1, weightsize), comlex)))[0][1]

    res = minimize(lambda x: vx(x), x0, method='SLSQP', bounds=bond)
    # method='SLSQP'
    print(-res.fun)
    print(res.success)
    print(res.x)
    res.x = np.ceil(res.x)
    # result = np.ceil(np.dot(res.x,complex))
    return res.x


def get_grad(img_data):
    '''
    对图像的特征进行提取
    :param img_data: 图像信息
    :param flag: 奇数点还是偶数点
    :return:
    '''
    row, col = img_data.shape
    size = int((row * col) / 2)

    v = np.zeros((row, col))
    h = np.zeros((row, col))
    for i in range(2, row - 2):
        for j in range(2, col - 2):
            # 像素上下左右四个像素
            v1 = int(img_data[i - 1][j])
            v2 = int(img_data[i][j - 1])
            v3 = int(img_data[i + 1][j])
            v4 = int(img_data[i][j + 1])
            # 选中点
            x = int(img_data[i][j])
            # 其他九个点
            v5 = int(img_data[i - 2][j - 1])
            v6 = int(img_data[i - 1][j - 2])
            v7 = int(img_data[i + 1][j - 2])
            v8 = int(img_data[i + 2][j - 1])
            v9 = int(img_data[i + 2][j + 1])
            v10 = int(img_data[i + 1][j + 2])
            v11 = int(img_data[i - 1][j + 2])
            v12 = int(img_data[i - 2][j + 1])

            if np.mod(i + j, 2) == 0:
                # 新点
                x1 = int(img_data[i + 1][j + 1])
                x2 = int(img_data[i + 1][j - 1])
                x3 = int(img_data[i - 1][j + 1])
                x4 = int(img_data[i + 1][j - 1])
                x5 = int(img_data[i][j + 2])
                x6 = int(img_data[i][j - 2])
                h[i][j] = np.round((6 * np.sum([x1 - x2, x3 - x4]) + 2 * np.sum([x5 - x6])) / 4)
                y1 = int(img_data[i + 1][j + 1])
                y2 = int(img_data[i - 1][j + 1])
                y3 = int(img_data[i + 1][j - 1])
                y4 = int(img_data[i - 1][j - 1])
                y5 = int(img_data[i + 2][j])
                y6 = int(img_data[i - 2][j])
                # y7 = int(img_data[i-2][j-1])
                # y9 = int(img_data[i-2][j-2])
                # y10 = int(img_data[i-2][j+2])

                v[i][j] = np.round((6 * np.sum([y1 - y2, y3 - y4]) + 2 * np.sum([y5 - y6])) / 4)
                # if i -3<0:
                #     v[i-1][j] =np.round((5*(y7+v12)+2*v1)/3+(3*(v2+v4)+v1+v3)/2)
                # if i-3>=0:
                #     y8 = int(img_data[i-3][j])
                #     y11 =int(img_data[i-3][j+1])
                #     y12 = int(img_data[i-3][j-1])
                #     v1 = np.round((6*np.sum([v4-v12,v2-y7])+2*np.sum(v3-y8))/4)
                #
                # else:
                #     v1 =np.round((5*(y7+v12)+2*v1)/3+(3*(v2+v4)+v1+v3)/2)
                # if i-4>=0:
                #     y11 = int(img_data[i - 3][j + 1])
                #     y12 = int(img_data[i - 3][j - 1])
                #     y13 = int(img_data[i-4][j])
                #     v3 = np.round((6 * np.sum([v12 - y11, y7 - y12]) + 2 * (y10 - y9)) / 4)

            if np.mod(i + j, 2) == 1:
                y1 = int(img_data[i + 2][j + 1])
                y2 = int(img_data[i + 2][j - 1])
                y3 = int(img_data[i - 2][j + 1])
                y4 = int(img_data[i + 2][j - 1])
                y5 = int(img_data[i + 1][j + 2])
                y6 = int(img_data[i + 1][j - 2])
                y7 = int(img_data[i - 1][j + 2])
                y8 = int(img_data[i - 1][j - 2])
                y9 = int(img_data[i][j + 1])
                y10 = int(img_data[i][j - 1])
                h[i][j] = np.round(
                    (np.sum([y1 - y2, y3 - y4]) + np.sum([y5 - y6, y7 - y8]) + 10 * np.sum([y9 - y10])) / 4)
                y1 = int(img_data[i + 1][j + 2])
                y2 = int(img_data[i - 1][j + 2])
                y3 = int(img_data[i + 1][j - 2])
                y4 = int(img_data[i - 1][j - 2])
                y5 = int(img_data[i + 2][j + 1])
                y6 = int(img_data[i - 2][j + 1])
                y7 = int(img_data[i + 2][j - 1])
                y8 = int(img_data[i - 2][j - 1])
                y9 = int(img_data[i + 1][j])
                y10 = int(img_data[i - 1][j])
                v[i][j] = np.round(
                    (np.sum([y1 - y2, y3 - y4]) + np.sum([y5 - y6, y7 - y8]) + 10 * np.sum([y9 - y10])) / 4)

            # if flag == 1:
            #     if np.mod(i + j, 2) == 1:
            #         # 新点
            #         x1 = int(img_data[i + 1][j + 1])
            #         x2 = int(img_data[i + 1][j - 1])
            #         x3 = int(img_data[i - 1][j + 1])
            #         x4 = int(img_data[i + 1][j - 1])
            #         x5 = int(img_data[i][j + 2])
            #         x6 = int(img_data[i][j - 2])
            #         h = np.round((6 * np.sum([x1 - x2, x3 - x4]) + 2 * np.sum([x5 - x6])) / 4)
            #         x1 = int(img_data[i + 1][j + 1])
            #         x2 = int(img_data[i - 1][j + 1])
            #         x3 = int(img_data[i + 1][j - 1])
            #         x4 = int(img_data[i - 1][j - 1])
            #         x5 = int(img_data[i + 2][j])
            #         x6 = int(img_data[i - 2][j])
            #         v[i][j] = np.round((6 * np.sum([x1 - x2, x3 - x4]) + 2 * np.sum([x5 - x6])) / 4)
            #     if np.mod(i + j, 2) == 0:
            #         y1 = int(img_data[i + 2][j + 1])
            #         y2 = int(img_data[i + 2][j - 1])
            #         y3 = int(img_data[i - 2][j + 1])
            #         y4 = int(img_data[i + 2][j - 1])
            #         y5 = int(img_data[i + 1][j + 2])
            #         y6 = int(img_data[i + 1][j - 2])
            #         y7 = int(img_data[i - 1][j + 2])
            #         y8 = int(img_data[i - 1][j - 2])
            #         y9 = int(img_data[i][j + 1])
            #         y10 = int(img_data[i][j - 1])
            #         h[i][j] = np.round((np.sum([y1 - y2, y3 - y4]) + np.sum([y5 - y6, y7 - y8]) + 10 * np.sum([y9 - y10])) / 4)
            #         y1 = int(img_data[i + 1][j + 2])
            #         y2 = int(img_data[i - 1][j + 2])
            #         y3 = int(img_data[i + 1][j - 2])
            #         y4 = int(img_data[i - 1][j - 2])
            #         y5 = int(img_data[i + 2][j + 1])
            #         y6 = int(img_data[i - 2][j + 1])
            #         y7 = int(img_data[i + 2][j - 1])
            #         y8 = int(img_data[i - 2][j - 1])
            #         y9 = int(img_data[i + 1][j])
            #         y10 = int(img_data[i - 1][j])
            #         v = np.round((np.sum([y1 - y2, y3 - y4]) + np.sum([y5 - y6, y7 - y8]) + 10 * np.sum([y9 - y10])) / 4)

    return v, h


def get_feature2(img_data, flag, ksize):
    '''
    对图像的特征进行提取
    :param img_data: 图像信息
    :param flag: 奇数点还是偶数点
    :return:
    '''
    row, col = img_data.shape
    size = int((row * col) / 2)
    F = np.zeros((ksize, size))
    # 预测点
    predict = np.zeros((row, row))
    # 误差值
    erromap = np.zeros((row, row))
    errolist = np.zeros((1, size))[0]
    index = 0
    for i in range(2, row - 2):
        for j in range(2, col - 2):
            # 像素上下左右四个像素
            v1 = int(img_data[i - 1][j])
            v2 = int(img_data[i][j - 1])
            v3 = int(img_data[i + 1][j])
            v4 = int(img_data[i][j + 1])
            # 选中点
            x = int(img_data[i][j])
            # 其他九个点
            v5 = int(img_data[i - 2][j - 1])
            v6 = int(img_data[i - 1][j - 2])
            v7 = int(img_data[i + 1][j - 2])
            v8 = int(img_data[i + 2][j - 1])
            v9 = int(img_data[i + 2][j + 1])
            v10 = int(img_data[i + 1][j + 2])
            v11 = int(img_data[i - 1][j + 2])
            v12 = int(img_data[i - 2][j + 1])
            # 左梯度和右梯度
            lg = np.array([[v5 - v1, v2 - v1], [v1 - v4, v3 - v4], [v2 - v3, v8 - v3], [v6 - v2, v7 - v2]])
            rg = np.array([[v12 - v1, v4 - v1], [v11 - v4, v10 - v4], [v4 - v3, v9 - v3], [v1 - v2, v3 - v2]])
            # # 特征
            f1 = np.max([v1, v2, v3, v4])
            f2 = np.min([v1, v2, v3, v4])
            sod1 = abs(v2 + v4 + v5 + v12 - 4 * v1)
            sod2 = abs(v1 + v3 + v6 + v7 - 4 * v2)
            sod3 = abs(v2 + v4 + v8 + v9 - 4 * v3)
            sod4 = abs(v1 + v3 + v10 + v11 - 4 * v4)
            f3 = np.sum([sod1, sod2, sod3, sod4])
            f4_arr = [abs(v1 - v2), abs(v2 - v3), abs(v3 - v4), abs(v4 - v1)]
            f4 = np.sum(f4_arr)
            p1 = (math.modf(np.average([v1, v2, v3, v4])))[0]
            p = np.ceil(np.average([v1, v2, v3, v4])) if p1 >= 0.5 else np.floor(np.average([v1, v2, v3, v4]))
            p3 = np.ceil(np.average([v1, v2, v3, v4]))
            f5_arr = [abs(v6 - v7), abs(v5 - v2), abs(v2 - v8), abs(v1 - v3), abs(v12 - v4), abs(v4 - v9),
                      abs(v11 - v10), abs(v5 - v12), abs(v6 - v1), abs(v1 - v11), abs(v2 - v4), abs(v7 - v3),
                      abs(v3 - v10), abs(v8 - v9)]
            f5 = np.sum(f5_arr)
            new_f5 = np.sum(np.square(f4_arr - np.mean(f4_arr))) / 4
            f6_arr = [abs(p - v1), abs(p - v2), abs(p - v3), abs(p - v4), abs(p - v5), abs(p - v6), abs(p - v7),
                      abs(p - v8), abs(p - v9), abs(p - v10), abs(p - v11), abs(p - v12)]
            f6 = np.sum(f6_arr)
            new_f6 = np.sum(np.squeeze(np.array([v1, v2, v3, v4]) - p)) / 4
            f7 = np.sum(np.sqrt(np.sum(np.square(lg), axis=1)))
            f8 = np.sum(np.sqrt(np.sum(np.square(rg), axis=1)))
            gradDiff = []
            gradDiff2 = []
            for s in range(3):
                for q in range(s, 4):
                    gradDiff.append(lg[s] - lg[q])
                    gradDiff2.append(rg[s] - rg[q])
            # print(gradDiff, gradDiff2)
            gradDiff = np.array(gradDiff)
            gradDiff2 = np.array(gradDiff2)
            f9 = np.sum(np.sqrt(np.sum(np.square(gradDiff), axis=1)))
            f10 = np.sum(np.sqrt(np.sum(np.square(gradDiff2), axis=1)))
            # a = np.array([f1, f2, f4, f3, f10, f9, f8, f7, f5, f6])
            a = np.array([f1, f2, f3, f4, f5, f6, f7, f8, f9, f10])
            # a = np.array([f1,f2,f3,f4,new_f5,new_f6,f7,f8,f9,f10])
            #
            if np.mod(i + j, 2) == 0 and flag == 0:
                # print(a)
                # a = a.reshape(-1, 1)
                # scaler = MinMaxScaler(feature_range=(-1,1))
                # a = scaler.fit_transform(a)
                # a =a.flatten()
                # a =(a+1)*500
                F[:, index] = a
                errolist[index] = int(img_data[i][j]) - int(p)
                index += 1
                erromap[i][j] = int(img_data[i][j]) - int(p)

            if np.mod(i + j, 2) == 1 and flag == 1:
                # a = a.reshape(-1, 1)
                # scaler = MinMaxScaler()
                # a = scaler.fit_transform(a)
                # a = a.flatten()
                # a = (a + 1) * 500
                F[:, index] = a
                errolist[index] = int(img_data[i][j]) - int(p)
                index += 1
                erromap[i][j] = int(img_data[i][j]) - int(p)

    print('index', index)
    print(F.shape)
    F = F[:, :index]
    errolist = errolist[:index]
    return F, errolist, index


def complexity_map(img_data, label, flags):
    cm = np.ones(img_data.shape) * 999
    A, B = img_data.shape
    count = 0
    for i in range(2, A - 2):
        for j in range(2, B - 2):
            if np.mod(i + j, 2) == 0 and flags == 0:
                cm[i][j] = int(label[count])
                count = count + 1
            if np.mod(i + j, 2) == 1 and flags == 1:
                cm[i][j] = int(label[count])
                count = count + 1
    return cm


def cal_entropy(imgs, label, ks, flags):
    A, B = imgs.shape
    his = []
    count = 0
    entropy = []
    for i in range(ks):
        his.append([])
    for i in range(2, A - 2):
        for j in range(2, B - 2):
            v1 = int(imgs[i - 1][j])
            v2 = int(imgs[i + 1][j])
            v3 = int(imgs[i][j + 1])
            v4 = int(imgs[i][j - 1])
            p1 = (math.modf(np.average([v1, v2, v3, v4])))[0]
            p = np.ceil(np.average([v1, v2, v3, v4])) if p1 >= 0.5 else np.floor(np.average([v1, v2, v3, v4]))
            e = int(imgs[i][j]) - p
            if flags == 0 and np.mod(i + j, 2) == 0:

                his[label[count]].append(e)
                count = count + 1
            elif flags == 1 and np.mod(i + j, 2) == 1:
                his[label[count]].append(e)
                count = count + 1

    for i in range(ks):
        e = 0
        c = Counter(his[i])
        total = len(his[i])
        for j in c.values():
            pro = int(j) / total
            e = e + pro * math.log(1 / pro, 2)
        entropy.append(e)
    print(entropy)
    entropy_sort = sorted(entropy)

    return entropy_sort


def cal_aux(checklist, data_length, scale, re, lcm, flags):
    cl = 0
    test = []
    for i in range(16):
        test.append(i)
    checklist = np.array(checklist) + 1
    # checklist = np.array(test)+1
    print('incheck', checklist)
    # a = np.ceil(np.log2(np.max(checklist)))
    if flags == 0:
        for i in range(16):
            #
            if re[i] == 250:
                scale = scale - 1
            if checklist[i] != i:
                cl = cl + np.ceil(np.log2(checklist[i]))
        if np.sum(lcm) == 0:
            aux = scale * 3 + 4 + 1 + 17 + cl + 4
        else:
            aux = scale * 3 + 4 + 1 + data_length * 8 + 17 + 17 + cl + 4
    if flags == 1:  # 根据寻优的bins更新辅助信息的长度
        for i in range(16):
            if re[i] < 250 and checklist[i] > i:
                cl = cl + np.ceil(np.log2(checklist[i]))
            if re[i] == 250:
                scale = scale - 1
                print('scale', scale)
        if np.sum(lcm) == 0:
            aux = scale * 3 + 4 + 1 + 17 + cl + 4
        else:
            aux = scale * 3 + 4 + 1 + data_length * 8 + 17 + 17 + cl + 4
    print('The aux is ', flags, ' ', aux)
    return aux


def re_hs(k, row, col, cm, flag, em):
    Hs = np.zeros((511, k))
    # index = 0
    for i in range(2, row - 2):
        for j in range(2, col - 2):
            if int(cm[i][j]) != 999:
                if np.mod(i + j, 2) == 0 and flag == 0:
                    if em[i][j] != 999:
                        Hs[int(em[i][j] + 255)][int(cm[i][j])] += 1
                    # index += 1
                if np.mod(i + j, 2) == 1 and flag == 1:
                    if em[i][j] != 999:
                        Hs[int(em[i][j] + 255)][int(cm[i][j])] += 1
                    # index += 1
    return Hs


def insert_msg(em, cm, bin, img_hide3, secret, ec3, flag3):
    '''
        em误差矩阵
        Dbis复杂度矩阵
        bin最佳区间
        img_hide图形矩阵
        secret嵌入矩阵
        插入需要插入的信息
    '''
    index = 0
    index2 = 0
    row, col = img_hide3.shape
    for i in range(2, row - 2):
        for j in range(2, col - 2):
            if np.mod(i + j, 2) == 0 and flag3 == 0 and ec3 > 0:
                ks = cm[i][j] - 1
                if em[i][j] == bin[int(ks)]:
                    ec3 = ec3 - 1
                    img_hide3[i][j] += secret[i][j]
                    if secret[i][j] == 1:
                        index2 += 1
                if em[i][j] == -bin[int(ks)] - 1:
                    ec3 = ec3 - 1
                    img_hide3[i][j] -= secret[i][j]
                    if secret[i][j] == 1:
                        index2 += 1
                if em[i][j] > bin[int(ks)]:
                    img_hide3[i][j] += 1
                    index += 1
                if em[i][j] < -bin[int(ks)] - 1:
                    img_hide3[i][j] -= 1
                    index += 1
            if np.mod(i + j, 2) == 1 and flag3 == 1 and ec3 > 0:
                ks = cm[i][j] - 1
                if em[i][j] == bin[int(ks)]:
                    ec3 = ec3 - 1
                    img_hide3[i][j] += secret[i][j]
                    if secret[i][j] == 1:
                        index2 += 1
                if em[i][j] == -bin[int(ks)] - 1:
                    ec3 = ec3 - 1
                    img_hide3[i][j] -= secret[i][j]
                    if secret[i][j] == 1:
                        index2 += 1
                if em[i][j] > bin[int(ks)]:
                    img_hide3[i][j] += 1
                    index += 1
                if em[i][j] < -bin[int(ks)] - 1:
                    img_hide3[i][j] -= 1
                    index += 1

    print("偏移数量", index)
    print('偏移点数量', index2)
    return img_hide3, ec3


def instert_ms(em, cm, img_hide3, secret, RateList, flag3, PZlist, typemap):
    row, col = img_hide3.shape
    index = 0
    for i in range(2, row - 2):
        for j in range(2, col - 2):
            m = int(cm[i][j])
            types = 0
            if m != 999:
                if RateList[m] != 0:
                    P = PZlist[m][0]
                    Z = PZlist[m][1]
                    types = 1
                else:
                    types = 0
            if np.mod(i + j, 2) == 0 and flag3 == 0 and types == 1 and typemap[i][j] != 4:
                for k in range(len(P)):
                    # if em[i][j] == (P[k]-255):
                    #     img_hide3[i][j] +=secret[i][j]
                    #     ec3-=1
                    # tmp = img_hide3[i][j].copy()
                    if P[k] > Z[k] and RateList[m] > 0:
                        # if em[index] == (P[k] - 255):
                        if em[i][j] == (P[k] - 255) and RateList[m] > 0:
                            img_hide3[i][j] -= secret[i][j]
                            RateList[m] -= 1
                        if em[i][j] > (Z[k] - 255) and em[i][j] < (P[k] - 255):
                            # if em[index]  > (Z[k] - 255) and em[index]  < (P[k] - 255):
                            img_hide3[i][j] -= 1
                            # index += 1
                    if P[k] < Z[k] and RateList[m] > 0:
                        if em[i][j] == (P[k] - 255):
                            # if em[index]  == (P[k] - 255):
                            img_hide3[i][j] += secret[i][j]
                            RateList[m] -= 1
                        if em[i][j] < (Z[k] - 255) and em[i][j] > (P[k] - 255):
                            # if em[index] < (Z[k] - 255) and em[index]> (P[k] - 255):
                            img_hide3[i][j] += 1
                index += 1
            if np.mod(i + j, 2) == 1 and flag3 == 1 and types == 1 and typemap[i][j] != 4:
                for k in range(len(P)):
                    # if em[i][j] == (P[k] - 255):
                    #     img_hide3[i][j] += secret[i][j]
                    #     ec3 -=1
                    if P[k] > Z[k] and RateList[m] > 0:
                        # if em[index] == (P[k] - 255):
                        if em[i][j] == (P[k] - 255) and RateList[m] > 0:
                            img_hide3[i][j] -= secret[i][j]
                            RateList[m] -= 1
                        if em[i][j] > (Z[k] - 255) and em[i][j] < (P[k] - 255):
                            # if em[index] > (Z[k] - 255) and em[index] < (P[k] - 255):
                            img_hide3[i][j] -= 1
                            # index += 1
                    if P[k] < Z[k] and RateList[m] > 0:
                        if em[i][j] == (P[k] - 255) and RateList[m] > 0:
                            # if em[index] == (P[k] - 255):
                            img_hide3[i][j] += secret[i][j]
                            RateList[m] -= 1
                        if em[i][j] < (Z[k] - 255) and em[i][j] > (P[k] - 255):
                            # if em[index] < (Z[k] - 255) and em[index] > (P[k] - 255):
                            img_hide3[i][j] += 1
                index += 1
    return img_hide3, RateList


def ga_searchbin(H, rate):
    T = 300
    G = 100
    maxL = 25
    V, USE = initpopulation(H, maxL, G)
    R, D, Layer = caculateRD(V, maxL, G, H)

    Best_V, Best_dist, feature = find_best(R, D, G, rate, maxL, V)

    Best_V, D, t_D, features = divide_rate(T, G, V, maxL, H, USE, rate, Best_V, feature, Best_dist)

    S_Rate, S_dist, PzList = Choose_PZ(Best_V, H, maxL)

    return S_Rate, S_dist, PzList


def getModifyMap(PzList):
    PZ = []
    for k in range(len(PzList)):
        if len(PzList[k][0]) != 0:
            P = PzList[k][0]
            Z = PzList[k][1]
            P = np.sort(P)
            Z = np.sort(Z)
            for i in range(len(P)):
                for j in range(len(P)):
                    if P[i] < Z[i]:
                        if P[i] + 1 <= Z[i] - 1:
                            if P[i] < P[j] < Z[i]:
                                P[j] += 1
                                Z[j] += 1
                    else:
                        if P[i] - 1 >= Z[i] + 1:
                            if P[i] > P[j] > Z[i]:
                                P[j] -= 1
                                Z[j] -= 1
            PZ.append([P, Z])
        else:
            PZ.append([[], []])
    return PZ


def danci(danci_img, flags, ks, ecfinals):
    danci_img, lcm, halfsize, data = Over_flow(danci_img, flags)
    # 数组长度
    data_length = len(data)
    # 获取图片的坐标的长宽
    row, col = danci_img.shape
    # 初始图像数据,获取误差以及按照图像的复杂度进行分类
    v, h = get_grad(danci_img)
    label, em, typemap = get_feature(danci_img, flags, 10, v, h)
    label, check = cal_entropy(danci_img, label, ks, flags, em)
    cm = complexity_map(danci_img, label, flags)
    hs = re_hs(16, row, col, cm, flags, em)
    # check = cal_entropy(hs, ks)
    R = np.zeros(16)
    anx = cal_aux(check, data_length, ks, R, lcm, flags)
    # anx = test[0]
    ec1 = np.ceil(ecfinals / 2)
    print('ec1', ec1)
    hs = hs.T
    S_Rate, S_dist, PzList = ga_searchbin(hs, ec1)
    print('此时最佳', S_Rate)
    print('最佳选点', PzList)
    # PzList = getModifyMap(PzList)
    # # img_hide记录修改过后的图像坐标
    img_hide1 = copy.deepcopy(danci_img)
    # # 嵌入的数据secrt_msg[0][index]
    secret_info = secret_msg(row, col)
    # # 嵌入数据之后的误差图像
    img_hide1, RateList = instert_ms(em, cm, img_hide1, secret_info, S_Rate, flags, PzList, typemap)
    # # lsb插入辅助信息
    anx_secret = secret_msg(row, col)
    img_hide1 = Lsb_insert(row, col, anx, img_hide1, flags, anx_secret)
    return img_hide1, RateList


def plt_make(x, psnr):
    # x = np.array([0.0267, 0.05, 0.1, 0.20, 0.3, 0.40, 0.499, 0.60, 0.7])
    y = psnr
    plt.plot(x, y, '-r', label='psnr')
    plt.plot(x, y, '.b')
    plt.title('lena psnr')
    plt.xlabel('ec', color='#1C2833')
    plt.ylabel('psnr', color='#1C2833')
    plt.legend(loc='upper left')
    plt.grid()
    plt.show()


def get_em(img_data, flag, v, h):
    row, col = img_data.shape
    size = int((row * col) / 2)
    # 预测点
    predict = np.zeros((row, row))
    # 误差值
    erromap = np.zeros((row, col))
    index = 0
    typemap = np.zeros((row, col))
    for i in range(2, row - 2):
        for j in range(2, col - 2):
            # 像素上下左右四个像素
            v1 = int(img_data[i - 1][j])
            v2 = int(img_data[i][j - 1])
            v3 = int(img_data[i + 1][j])
            v4 = int(img_data[i][j + 1])
            # 选中点
            x = int(img_data[i][j])
            # 其他九个点
            v5 = int(img_data[i - 2][j - 1])
            v6 = int(img_data[i - 1][j - 2])
            v7 = int(img_data[i + 1][j - 2])
            v8 = int(img_data[i + 2][j - 1])
            v9 = int(img_data[i + 2][j + 1])
            v10 = int(img_data[i + 1][j + 2])
            v11 = int(img_data[i - 1][j + 2])
            v12 = int(img_data[i - 2][j + 1])
            # 左梯度和右梯度
            lg = np.array([[v5 - v1, v2 - v1], [v1 - v4, v3 - v4], [v2 - v3, v8 - v3], [v6 - v2, v7 - v2]])
            rg = np.array([[v12 - v1, v4 - v1], [v11 - v4, v10 - v4], [v4 - v3, v9 - v3], [v1 - v2, v3 - v2]])
            # # 特征
            f1 = np.max([v1, v2, v3, v4])
            f2 = np.min([v1, v2, v3, v4])
            sod1 = abs(v2 + v4 + v5 + v12 - 4 * v1)
            sod2 = abs(v1 + v3 + v6 + v7 - 4 * v2)
            sod3 = abs(v2 + v4 + v8 + v9 - 4 * v3)
            sod4 = abs(v1 + v3 + v10 + v11 - 4 * v4)
            f3 = np.sum([sod1, sod2, sod3, sod4])
            f4_arr = [abs(v1 - v2), abs(v2 - v3), abs(v3 - v4), abs(v4 - v1)]
            f4 = np.sum(f4_arr)
            # p2 = np.average([abs(v1 - v2), abs(v2 - v3), abs(v3 - v4), abs(v4 - v1)])
            p1 = (math.modf(np.average([v1, v2, v3, v4])))[0]
            p = np.ceil(np.average([v1, v2, v3, v4])) if p1 >= 0.5 else np.floor(np.average([v1, v2, v3, v4]))
            # f5_arr = [p2 - abs(v1 - v2), p2 - abs(v2 - v3), p2 - abs(v3 - v4), p2 - abs(v4 - v1)]
            # f5 = np.average(np.square(f5_arr))
            # f6_arr = [p - v1, p - v2, p - v3, p - v4]
            # f6 = np.average(np.square(f6_arr))
            f5_arr = [abs(v6 - v7), abs(v5 - v2), abs(v2 - v8), abs(v1 - v3), abs(v12 - v4), abs(v4 - v9),
                      abs(v11 - v10), abs(v5 - v12), abs(v6 - v1), abs(v1 - v11), abs(v2 - v4), abs(v7 - v3),
                      abs(v3 - v10), abs(v8 - v9)]
            f5 = np.sum(f5_arr)
            f6_arr = [abs(p - v1), abs(p - v2), abs(p - v3), abs(p - v4), abs(p - v5), abs(p - v6), abs(p - v7),
                      abs(p - v8), abs(p - v9), abs(p - v10), abs(p - v11), abs(p - v12)]
            f6 = np.sum(f6_arr)
            f7 = np.sum(np.sqrt(np.sum(np.square(lg), axis=1)))
            f8 = np.sum(np.sqrt(np.sum(np.square(rg), axis=1)))
            gradDiff = []
            gradDiff2 = []
            for s in range(3):
                for q in range(s, 4):
                    gradDiff.append(lg[s] - lg[q])
                    gradDiff2.append(rg[s] - rg[q])
            # print(gradDiff, gradDiff2)
            gradDiff = np.array(gradDiff)
            gradDiff2 = np.array(gradDiff2)
            f9 = np.sum(np.sqrt(np.sum(np.square(gradDiff), axis=1)))
            f10 = np.sum(np.sqrt(np.sum(np.square(gradDiff2), axis=1)))
            a = np.array([f1, f2, f4, f3, f10, f9, f8, f7, f5, f6])
            # a = np.array([ f2, f4, f3, f10, f9, f8, f7, f5, f6])
            if i >= 4 and j >= 4:
                w1 = 1 / (1 + abs(v[i][j]) + 2 * abs(v[i - 1][j]) + abs(v[i - 2][j]))
                w2 = 1 / (1 + abs(v[i][j]) + 2 * abs(v[i + 1][j]) + abs(v[i + 2][j]))
                w3 = 1 / (1 + abs(h[i][j]) + 2 * abs(h[i][j - 1]) + abs(h[i][j - 2]))
                w4 = 1 / (1 + abs(h[i][j]) + 2 * abs(h[i][j + 1]) + abs(h[i][j + 2]))
                warr = [w1 * v1, w2 * v3, w3 * v2, w4 * v4]
                predx = np.round(np.sum(warr) / np.sum([w1, w2, w3, w4]))
            else:
                predx = p
            if np.mod(i + j, 2) == 0 and flag == 0:
                # print(a)
                prevalue = 0
                xmax = np.max([predx, p])
                xmin = np.min([predx, p])
                if xmax == xmin:
                    prevalue = xmin
                    typemap[i][j] = 1
                elif img_data[i][j] <= xmin:
                    prevalue = xmin
                    typemap[i][j] = 2
                elif img_data[i][j] >= xmax:
                    prevalue = xmax
                    typemap[i][j] = 3
                else:
                    typemap[i][j] = 4

                # errolist[index] = int(img_data[i][j]) - int(prevalue)
                index += 1
                if prevalue != 0:
                    erromap[i][j] = int(img_data[i][j]) - int(prevalue)

            if np.mod(i + j, 2) == 1 and flag == 1:
                prevalue = 0
                xmax = np.max([predx, p])
                xmin = np.min([predx, p])
                if xmax == xmin:
                    prevalue = xmin
                    typemap[i][j] = 1
                elif img_data[i][j] <= xmin:
                    prevalue = xmin
                    typemap[i][j] = 2
                elif img_data[i][j] >= xmax:
                    prevalue = xmax
                    typemap[i][j] = 3
                else:
                    typemap[i][j] = 4
                if prevalue != 0:
                    erromap[i][j] = int(img_data[i][j]) - int(prevalue)
    return erromap, typemap


class MyProblem(ea.Problem):  # 继承Problem父类
    def __init__(self, em, F):
        name = 'MyProblem'  # 初始化name（函数名称，可以随意设置）
        M = 1  # 初始化M（目标维数）
        maxormins = [-1]  # 初始化maxormins（目标最小最大化标记列表，1：最小化该目标；-1：最大化该目标）
        Dim = 10  # 初始化Dim（决策变量维数）
        varTypes = [1] * Dim  # 初始化varTypes（决策变量的类型，元素为0表示对应的变量是连续的；1表示是离散的）
        lb = [-255] * Dim  # 决策变量下界
        ub = [255] * Dim  # 决策变量上界
        lbin = [1] * Dim  # 决策变量下边界（0表示不包含该变量的下边界，1表示包含）
        ubin = [1] * Dim  # 决策变量上边界（0表示不包含该变量的上边界，1表示包含）
        self.em = em
        self.F = F
        # 调用父类构造方法完成实例化
        ea.Problem.__init__(self, name, M, maxormins, Dim, varTypes, lb, ub, lbin, ubin)

    def evalVars(self, Vars):  # 目标函数
        x = Vars.astype(int)
        # print(x.shape)
        em = self.em
        cm = self.F
        f = []
        for i in range(len(x[:, 0])):
            data = np.corrcoef(abs(em), abs(np.dot(x[i, :], cm)))[0][1]
            f.append(data)
        # 采用可行性法则处理约束
        f = np.array(f)
        row = f.shape[0]
        f = f.reshape(row, -1)
        # print(f.shape)
        return f

    def calReferObjV(self):  # 设定目标数参考值（本问题目标函数参考值设定为理论最优值）
        referenceObjV = np.array([[1]])
        return referenceObjV


def Gatest(em, cm):
    problem = MyProblem(em, cm)  # 生成问题对象
    # 快速构建算法
    algorithm = ea.soea_DE_currentToBest_1_bin_templet(problem,
                                                       ea.Population(Encoding='RI', NIND=100),
                                                       MAXGEN=400,  # 最大进化代数。
                                                       logTras=0)  # 表示每隔多少代记录一次日志信息，0表示不记录。
    algorithm.mutOper.F = 0.7  # 差分进化中的参数F。
    algorithm.recOper.XOVR = 0.7  # 交叉概率。
    # 先验知识
    prophetVars = np.ones(10)  # 假设已知[0.4, 0.2, 0.4]为一组比较优秀的变量。
    # 求解
    res = ea.optimize(algorithm, prophet=prophetVars, verbose=True, drawing=1, outputMsg=True, drawLog=True,
                      saveFlag=False)
    print(res)
    return res


def featuretest(img_data, flag):
    '''
    对图像的特征进行提取
    :param img_data: 图像信息
    :param flag: 奇数点还是偶数点
    :return:
    '''
    row, col = img_data.shape
    size = int((row * col) / 2)
    # 预测点
    u = np.zeros(row * row)
    errolist = np.zeros(row * row)
    index = 0
    for i in range(2, row - 2):
        for j in range(2, col - 2):
            # 像素上下左右四个像素
            v1 = int(img_data[i - 1][j])
            v2 = int(img_data[i][j - 1])
            v3 = int(img_data[i + 1][j])
            v4 = int(img_data[i][j + 1])
            # 选中点
            x = int(img_data[i][j])
            # 其他九个点
            v5 = int(img_data[i - 2][j - 1])
            v6 = int(img_data[i - 1][j - 2])
            v7 = int(img_data[i + 1][j - 2])
            v8 = int(img_data[i + 2][j - 1])
            v9 = int(img_data[i + 2][j + 1])
            v10 = int(img_data[i + 1][j + 2])
            v11 = int(img_data[i - 1][j + 2])
            v12 = int(img_data[i - 2][j + 1])

            # p1 = (math.modf(np.average([v1, v2, v3, v4])))[0]
            # p = np.ceil(np.average([v1, v2, v3, v4])) if p1 >= 0.5 else np.floor(np.average([v1, v2, v3, v4]))
            p = np.ceil(np.mean([v1, v2, v3, v4]))
            x1 = abs(v2 - v1)
            x2 = abs(v1 - v4)
            x3 = abs(v4 - v3)
            x4 = abs(v2 - v3)
            x5 = np.mean([x1, x2, x3, x4])
            xarr = np.array([x1, x2, x3, x4])
            #
            # #
            if np.mod(i + j, 2) == 0 and flag == 0:
                # print('shape',u.shape,index)
                u[index] = np.sum(np.square(xarr - x5)) / 4
                # print('ux',xarr-x5)
                # print('uxx',np.square(xarr-x5))
                # print('uxx2',u[index])
                # print(img_data[i][j],p,[i,j])
                # print('v',v1,v2,v3,v4)
                # print('x',x1,x2,x3,x4)
                # print('xx',np.average([x1,x2,x3,x4]))
                # print([i,j,index])
                # print('errolist',int(img_data[i][j]) - int(p))
                # print('u',u[index])
                errolist[index] = int(img_data[i][j]) - int(p)
                index += 1

            if np.mod(i + j, 2) == 1 and flag == 1:
                u[index] = np.sum(np.square(xarr - x5)) / 4
                errolist[index] = int(img_data[i][j]) - int(p)
                index += 1
            # u[index] = np.sum(np.square(xarr - x5)) / 4
            # errolist[index] = int(img_data[i][j]) - int(p)
            # index += 1

    print('index', index)
    u = u[:index]
    errolist = errolist[:index]
    return u, errolist, index


def get_complex_map(img, flag):
    '''
            计算图像的复杂度矩阵
            :param img: 图像
            :param flag: 奇数点还是偶数点
            :return:  复杂度矩阵
        '''
    row, col = img.shape
    # cv2.imshow('Lena', img)
    # cv2.waitKey(0)
    # print('row, col=', row, col)
    complex_map = np.zeros((row, col))
    for i in range(2, row - 2):
        for j in range(2, col - 2):
            # 计算复杂度，直接跟阈值key比较

            # if complex[i][j]
            # 像素上下左右四个像素
            v1 = int(img[i - 1][j])  # p2
            v2 = int(img[i][j - 1])  # p1
            v3 = int(img[i + 1][j])  # p4
            v4 = int(img[i][j + 1])  # p3
            # 选中点
            x = int(img[i][j])  # xi
            # 其他九个点
            v5 = int(img[i - 2][j - 1])  # p8
            v6 = int(img[i - 1][j - 2])  # p7
            v7 = int(img[i + 1][j - 2])  # p6
            v8 = int(img[i + 2][j - 1])  # p5
            v9 = int(img[i + 2][j + 1])  # p12
            v10 = int(img[i + 1][j + 2])  # p11
            v11 = int(img[i - 1][j + 2])  # p10
            v12 = int(img[i - 2][j + 1])  # p9
            pixel12 = np.array([v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12])  # 像素周围的12个像素存到pixel12
            av = np.mean([v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12])  # 12像素的平均值，x0为论文中的m
            complex = np.sqrt(np.sum(np.square(pixel12 - av)) / 12)

            if np.mod(i + j, 2) == 0 and flag == 0:  # 偶数点
                complex_map[i][j] = complex
            if np.mod(i + j, 2) == 1 and flag == 1:  # 奇数点
                complex_map[i][j] = complex
    # print('complex_map0=', complex_map)
    # print('complex_map1=', complex_map1)
    # scio.savemat('C://Users//11748//Desktop//pythonmat/complex_map0.mat', {'complex_map0':complex_map0})
    # scio.savemat('C://Users//11748//Desktop//pythonmat/complex_map1.mat', {'complex_map1':complex_map1})
    return complex_map
